import os
import threading
from typing import Optional, List
import logging
from logging.handlers import TimedRotatingFileHandler


class Common:
    _first_init = True
    _instance_lock = threading.Lock()

    def __init__(self):
        if self._first_init:
            self._show_tab_base_ptr = None
            self._show_tab_light_ptr = None
            self._show_tab_motor_driver_ptr = None
            self._show_tab_motor_cut_ptr = None
            self._show_tab_sensor_ptr = None
            self._show_tab_window_ptr = None
            self._can_bus = None
            self.__udp_socket = None
            self.__udp_ip = ""
            self.__udp_port = 0
            self._recv_loop = False
            self.__bow_test_loop = True
            self._first_init = False
            self.__connect_type = None

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            with cls._instance_lock:
                if not hasattr(cls, '_instance'):
                    Common._instance = super().__new__(cls)
        return Common._instance

        # parse data segment

    @staticmethod
    def get_hex_data_h(hex_data):
        h_part = (hex_data >> 8) & 0xff
        return h_part

    @staticmethod
    def get_hex_data_l(hex_data):
        l_part = hex_data & 0xff
        return l_part

    @staticmethod
    def get_resource_path():
        cur_path = os.getcwd()
        cur_path = cur_path + os.sep + "resources" + os.sep
        # print("path = ", cur_path)
        if os.path.exists(cur_path):
            return cur_path
        else:
            return ""

    def set_udp_para(self, ip, port):
        self.__udp_ip = ip
        self.__udp_port = port

    def set_udp_socket(self, udp_socket):
        self.__udp_socket = udp_socket

    def get_udp_socket(self):
        return self.__udp_socket

    def is_init_connect(self):
        is_init_connect = False
        if self.__connect_type == 'udp':
            if self.__udp_socket is not None:
                is_init_connect = True
        elif self.__connect_type == 'can':
            if self._can_bus is not None:
                is_init_connect = True
        return is_init_connect

    def send_data(self, can_id: int, list_data: list):
        # 'id=1990,dlc=8,data=255,0,0,52,0,0,0,0'
        if self.__connect_type == 'udp':
            list_str = ''
            i = 0
            list_len = len(list_data)
            for item in list_data:
                list_str += str(item)
                if i + 1 < len(list_data):
                    list_str += ','
                i += 1
            msg = 'id=' + str(can_id) + ',' + 'dlc=8' + ',' + 'data=' +list_str
            self.__udp_socket.send_udp_data(msg)
            pass
        # Common().get_can_bus().send_data(0x224, [0xA5, 0x01, 0x3C, 0x02, 0X00, 0x00, 0x00, 0x00])
        elif self.__connect_type == 'can':
            self._can_bus.send_data(can_id, list_data)
        pass

    def set_connect_type(self, connect_type: str):
        self.__connect_type = connect_type

    def get_connect_type(self):
        return self.__connect_type

    def set_can_bus(self, can_bus):
        self._can_bus = can_bus

    def get_can_bus(self):
        return self._can_bus

    def set_thread_recv(self, bloop):
        self._recv_loop = bloop

    def get_thread_recv(self):
        return self._recv_loop

    def set_bow_test_loop(self, bloop):
        self.__bow_test_loop = bloop

    def get_bow_test_loop(self):
        return self.__bow_test_loop

    def get_show_tab_window(self):
        return self._show_tab_window_ptr

    def set_show_tab_window(self, ptr):
        self._show_tab_window_ptr = ptr
        pass

    def get_show_tab_base(self):
        return self._show_tab_base_ptr

    def set_show_tab_base(self, ptr):
        self._show_tab_base_ptr = ptr

    def set_show_tab_light(self, ptr):
        self._show_tab_light_ptr = ptr
        pass

    def get_show_tab_light(self):
        return self._show_tab_light_ptr

    def get_show_tab_motor_cut(self):
        return self._show_tab_motor_cut_ptr

    def set_show_tab_motor_cut(self, ptr):
        self._show_tab_motor_cut_ptr = ptr
        pass

    def get_show_tab_motor_driver(self):
        return self._show_tab_motor_driver_ptr

    def set_show_tab_motor_driver(self, ptr):
        self._show_tab_motor_driver_ptr = ptr

    def get_show_tab_sensor(self):
        return self._show_tab_sensor_ptr

    def set_show_tab_sensor(self, ptr):
        self._show_tab_sensor_ptr = ptr
        pass

    @staticmethod
    def setup_logging(log_dir='logs', log_file='app.log'):
        # 创建日志目录（如果不存在）
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)
        # 设置基础日志格式
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        )
        # 创建主logger
        logger = logging.getLogger()
        logger.setLevel(logging.INFO)
        # 创建按天轮转的Handler
        file_handler = TimedRotatingFileHandler(
            filename=os.path.join(log_dir, log_file),
            when='midnight',  # 每天午夜轮转
            interval=1,  # 每天
            backupCount=7,  # 保留7天日志
            encoding='utf-8'
        )
        file_handler.setFormatter(formatter)
        file_handler.suffix = "%Y-%m-%d"  # 日志文件后缀格式
        # 添加Handler到logger
        logger.addHandler(file_handler)
        # 可选：添加控制台输出
        # console_handler = logging.StreamHandler()
        # console_handler.setFormatter(formatter)
        # logger.addHandler(console_handler)
        return logger

